﻿//
//                       _oo0oo_
//                      o8888888o
//                      88" . "88
//                      (| -_- |)
//                      0\  =  /0
//                    ___/`---'\___
//                  .' \\|     |// '.
//                 / \\|||  :  |||// \
//                / _||||| -:- |||||- \
//               |   | \\\  -  /// |   |
//               | \_|  ''\---/''  |_/ |
//               \  .-\__  '-'  ___/-. /
//             ___'. .'  /--.--\  `. .'___
//          ."" '<  `.___\_<|>_/___.' >' "".
//         | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//         \  \ `_.   \_ __\ /__ _/   .-` /  /
//     =====`-.____`.___ \_____/___.-`___.-'=====
//                       `=---='
//
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//               佛祖保佑         永无BUG
//
//     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#region << 版 本 注 释 >>

/*----------------------------------------------------------------
* 类 名 称 ：View
* 类 描 述 ：
* 作    者 ：henrychang
* 创建时间 ：2019/1/22 15:38:36
*******************************************************************
* Copyright @ henrychang 2018. All rights reserved.
*******************************************************************
//----------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

using System;
using System.Collections.Generic;

namespace TouchFish.PureMVC
{
    public class View : IView
    {
        protected int multitonKey;

        protected Dictionary<int, IViewMediator> mediatorMap;

        protected Dictionary<int, IList<IObserver>> observerMap;

        public View(int key)
        {
            IView view;
            if (instanceMap.TryGetValue(key, out view) && multitonKey > 0)
                throw new Exception(ERROR_MSG + "  " + key);
            multitonKey = key;
            instanceMap.TryAdd(key, this);
            mediatorMap = new Dictionary<int, IViewMediator>();
            observerMap = new Dictionary<int, IList<IObserver>>();
            InitializeView();
        }

        protected virtual void InitializeView()
        {
        }

        public void RegisterObserver(int notificationId, IObserver observer)
        {
            IList<IObserver> observers;
            if (observerMap.TryGetValue(notificationId, out observers))
            {
                observers.Add(observer);
            }
            else
            {
                observerMap.TryAdd(notificationId, new List<IObserver> { observer });
            }
        }

        public void RemoveObserver(int notificationId, object notifyContext)
        {
            IList<IObserver> observers;
            if (observerMap.TryGetValue(notificationId, out observers))
            {
                for (int i = 0; i < observers.Count; i++)
                {
                    if (observers[i].CompareNotifyContext(notifyContext))
                    {
                        observers.RemoveAt(i);
                        break;
                    }
                }

                if (observers.Count == 0)
                    observerMap.Remove(notificationId);
            }
        }

        public void NotifyObservers(INotification notification)
        {
            IList<IObserver> observersRef;
            if (observerMap.TryGetValue(notification.NotifityId, out observersRef))
            {
                var observers = new List<IObserver>(observersRef);
                foreach (IObserver observer in observers)
                {
                    observer.NotifyObserver(notification);
                }
            }
        }

        public void RegisterMediator(IViewMediator mediator)
        {
            if (!mediatorMap.ContainsKey(mediator.MediatorId))
            {
                mediatorMap.Add(mediator.MediatorId, mediator);
                mediator.InitializeNotifier(multitonKey);
                int[] interests = mediator.ListNotificationInterests();

                if (interests.Length > 0)
                {
                    IObserver observer = new Observer(mediator.HandleNotification, mediator);
                    for (int i = 0; i < interests.Length; i++)
                    {
                        RegisterObserver(interests[i], observer);
                    }
                }
                mediator.OnRegister();
            }
        }

        public IViewMediator RetrieveMediator(int mediatorId)
        {
            IViewMediator mediator;
            return mediatorMap.TryGetValue(mediatorId, out mediator) ? mediator : null;
        }

        public IViewMediator RemoveMediator(int mediatorId)
        {
            IViewMediator mediator;
            if (mediatorMap.TryGetValue(mediatorId, out mediator))
            {
                mediatorMap.Remove(mediatorId);
                int[] interests = mediator.ListNotificationInterests();
                for (int i = 0; i < interests.Length; i++)
                {
                    RemoveObserver(interests[i], mediator);
                }
                mediator.OnRemove();
            }
            return mediator;
        }

        public bool HasMediator(int mediatorId)
        {
            return mediatorMap.ContainsKey(mediatorId);
        }

        #region Static

        public static IView GetInstance(int key)
        {
            IView view;
            if (!instanceMap.TryGetValue(key, out view))
            {
                view = new View(key);
            }
            return view;
        }

        public static void RemoveView(int key)
        {
            instanceMap.Remove(key);
        }

        protected static Dictionary<int, IView> instanceMap = new Dictionary<int, IView>();

        protected const string ERROR_MSG = "已经创建过 View Key值的实例";

        #endregion Static
    }
}